#pragma once
#include <sys/select.h>
#include "Socket.hpp"
#include "Log.hpp"
#include <memory>
#include <errno.h>
#include <string.h>
#include <string>
#include <poll.h>

static const int num = sizeof(fd_set) * 8;
class PollServer
{
public:
    PollServer(uint16_t port)
        :_port(port), _listensock(new TcpSocket), _isrunning(false), _num(num)
    {
    }
    void Init()
    {
        _rfds = new struct pollfd[_num];        //申请数组
        
        for(int i = 0; i < num; i++)            //初始化数组
        {
            _rfds[i].fd = -1;
            _rfds[i].events = 0;
            _rfds[i].revents = 0;
        }

        //  _rfds[10].fd = 10;     // fd关掉了，再去poll检测它，发现它也能就绪的
        _listensock->CreateListenSocket(_port);     //创建与关心listensock
        int listenfd = _listensock->GetSockfd();
        _rfds[listenfd].fd = listenfd;
        _rfds[listenfd].events |= POLLIN;

        _isrunning = true;
    }
    void PrintDebug()
    {
        std::cout << "关心的读事件的fd: ";
        for(int i = 0; i < num; i++)
            if(_rfds[i].fd != -1)
                std::cout << i << " ";
        std::cout << std::endl;
    }
    void Loop()
    {
        while(_isrunning)
        {
            int timeout = 5000;
            int n = poll(_rfds, num, timeout);
            PrintDebug();
            if(n == 0)
                lg.LogMessage(Warning, "timeout...\n");
            else if(n == -1)
            {
                // if(errno == EWOULDBLOCK)
                //     lg.LogMessage(Warning, "读事件没就绪\n");
                // else if(errno == EINTR)
                //     lg.LogMessage(Warning, "被信号中断\n");
                // else lg.LogMessage(Error, "select 错误\n");
                lg.LogMessage(Error, "poll 错误, errno: %d: %s\n", errno, strerror(errno));
            }
            else
            {
                lg.LogMessage(Info, "poll success, timeout: %d\n", timeout);
                HandlerEvent();
                std::cout << "n" << " " << n<< std::endl;
                
            }
        }
    }
    void HandlerEvent()
    {
        for(int i = 0; i < num; i++)
        {
            int fd = _rfds[i].fd;
            short revents = _rfds[i].revents;
                std::cout << fd << " " << revents<< std::endl;

            if(fd != -1 && (revents & POLLIN))   //fd是否被关心 && fd的POLLIN是否就绪
            {
                std::cout << fd << " " << revents<< std::endl;
                if(i == _listensock->GetSockfd()) //listensockfd
                {
                    std::string clientip;
                    uint16_t clientport;
                    Socket* sock = _listensock->AcceptConnection(clientip, clientport);
                    int fd = sock->GetSockfd();
                    if(fd < num)
                    {
                        _rfds[fd].fd = fd;
                        _rfds[fd].events |= POLLIN;       
                        lg.LogMessage(Info, "connect sccess, fd: %d\n", fd);
                    }
                    else
                    {
                        sock->CloseSockfd();
                        lg.LogMessage(Error, "fd full\n");
                    }
                    delete sock;        //不能这么写，这样fd被析构给释放了
                }
                else
                {
                std::cout << fd << " " << revents<< std::endl;
                    
                    char request[1024];
                    int n = recv(fd, request, 1023, 0);
                    if(n > 0)
                    {
                        request[n] = 0;
                        std::string response = "server# ";
                        response += request;
                        send(fd, response.c_str(), response.size(), 0);
                    }
                    else
                    {
                        lg.LogMessage(Warning, "client quit, errno:%d:%s\n", errno, strerror(errno));
                        _rfds[i].fd = -1;
                        _rfds[i].events = 0;
                        _rfds[i].revents = 0;
                    }
                }
            } 
        }
    }
    ~PollServer()
    {
        delete []_rfds;
    }
private:
    std::unique_ptr<Socket> _listensock;
    uint16_t _port;
    bool _isrunning;
    struct pollfd* _rfds;
    int _num;
};